import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.jws.soap.SOAPBinding.Style;
import javax.swing.AbstractButton;
import javax.swing.AbstractListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;



//import edu.stanford.ejalbert.BrowserLauncher;
//import edu.stanford.ejalbert.exception.BrowserLaunchingInitializingException;
//import edu.stanford.ejalbert.exception.UnsupportedOperatingSystemException;
import resources.Tools;
import resources.VariableAssignmentException;


/**
 * This class sets up a Container that contains menu systems, two JTables,
 * and listeners for the project
 * 
 * @author Marc Vandehey, Andrew Gifford, Bryan Gago
 */
@SuppressWarnings("serial")
public class Frame extends JFrame implements ActionListener, MouseListener{

static HashMap<String, String> nameMap = new HashMap<String,String>(); // Keep Track Of Names Used
static HashMap<String, String> altNameMap = new HashMap<String,String>(); // Keep Track of Cells That Are Named

ArrayList<String> users, fileNames;
ArrayList<JCheckBox> userCheck;
ArrayList<JLabel> fileLabels, deleteLabels;
JTable valTable;
static JTable formTable;
JLabel lblvv, lblfv;
JPanel middle, center, valPanel, formPanel;
JMenu file, show, reset, colors, save, load;
JMenuBar menuBar;
JMenuItem loadLocal, print, exit, clear, resetNames, moveVV, moveFV, hideFV, hideVV, equal, fullscreen, lines;
JMenuItem defaultProfile,watermelonProfile, valentineProfile, consoleProfile, halloweenProfile,coolestProfile,evenCooler;
JMenuItem changeName, copy, cut, delete,saveXML,saveCOMP,saveENCRYPT, saveCLOUD, loadCLOUD, deleteCLOUD;
static JMenuItem paste;
JPopupMenu popup;
JButton confirm, saveCancel, loadCancel;
ValTable tm1;
static FormTable tm2;
Container pane;
Point p;
int colSel, rowSel;
Boolean valFull = false;
Boolean formFull = false;
static String clipboard = null;
Style style = null;
int type;
int rowNumber, columnNumber;
static int errorRow;
static Boolean err = false;
JDialog userFrame, loadFrame;
int x,y;
static String dbPassword;
static boolean loggedIn;
static boolean cancelAction = false;

	/**
	 * Constructor for the Frame Window
	 */
	public Frame(){
		//Boolean success = userInit();
		fileLabels = new ArrayList<JLabel>();
		deleteLabels = new ArrayList<JLabel>();
		pane = getContentPane();
		pane.setLayout(new BorderLayout());
		formPanel = new JPanel();
		valPanel = new JPanel();
		valPanel.setLayout(new BorderLayout());
		formPanel.setLayout(new BorderLayout());
		middle = new JPanel();
		middle.setLayout(new GridLayout());
		
		formColors.defaultProfile();
		
		//ValTable Cell Renderer
			tm1 = new ValTable();
			valTable = new JTable(tm1){ 
				public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) 
				{ 
					Component c = super.prepareRenderer(renderer, rowIndex, vColIndex);
					if(err && rowIndex == errorRow)
					{
						c.setBackground(formColors.error);
						c.setFont(formColors.errorFont);
						c.setForeground(formColors.errorFg);
					}
					else{
						if (rowIndex % 2 == 0 && !isCellSelected(rowIndex, vColIndex) && formColors.isShaded)
						{
							c.setBackground(formColors.shading);
							c.setForeground(formColors.foreground);
							c.setFont(formColors.normalFont);
						}
						else if(isCellSelected(rowIndex, vColIndex))
						{
							c.setBackground(formColors.selection);
							c.setFont(formColors.selectFont);
							c.setForeground(formColors.selectFg);
							formTable.changeSelection(rowIndex, vColIndex, false, false);
						}
						else
						{
							c.setBackground(formColors.background); 
							c.setForeground(formColors.foreground);
							c.setFont(formColors.normalFont);
						}
					}
	
					String cell = this.getColumnName(vColIndex)+ rowIndex;
					if(!formTable.getValueAt(rowIndex, vColIndex).equals("") && rowIndex != errorRow){
						this.setToolTipText(cell + " (" + formTable.getValueAt(rowIndex, vColIndex) + ")");
					}
					else if(!formTable.getValueAt(rowIndex, vColIndex).equals("")){
						this.setToolTipText("ERROR AT " + cell);
					}
					else{
						this.setToolTipText(cell);
					}
					return c; 
				}
			};
		
		//FormTable CellRenderer
			tm2 = new FormTable();
			tm2.initiateValues();
			formTable = new JTable(tm2){ 
				public Component prepareRenderer(TableCellRenderer renderer, int rowIndex, int vColIndex) 
				{ 
					Component c = super.prepareRenderer(renderer, rowIndex, vColIndex);
					if (rowIndex % 2 == 0 && !isCellSelected(rowIndex, vColIndex) && formColors.isShaded)
					{
						c.setBackground(formColors.shading);
						c.setForeground(formColors.foreground);
						c.setFont(formColors.normalFont);
					}
					else if(isCellSelected(rowIndex, vColIndex))
					{
						c.setBackground(formColors.selection);
						c.setFont(formColors.selectFont);
						c.setForeground(formColors.selectFg);
						valTable.changeSelection(rowIndex, vColIndex, false, false);
					}
					else
					{
						c.setBackground(formColors.background); 
						c.setForeground(formColors.foreground);
						c.setFont(formColors.normalFont);
					}
					this.gridColor = formColors.grid;
	
					String cell = this.getColumnName(vColIndex)+ rowIndex;
					if(altNameMap.containsKey(cell)){
						this.setToolTipText(cell + " (" + altNameMap.get(cell) + ")");
					}
					else{
						this.setToolTipText(cell);
					}
					return c; 
	
				}
			};
		
		formTable.getModel().addTableModelListener(new FormTableModelListener(formTable, this));
		resetNameHash();
		
		// Right-Click Menu
			popup = new JPopupMenu();
		
			cut = new JMenuItem("Cut Cell", KeyEvent.VK_X);;
			cut.addActionListener(this);
			popup.add(cut);
		
			copy = new JMenuItem("Copy Cell", KeyEvent.VK_C);
			copy.addActionListener(this);
			popup.add(copy);
			
			paste = new JMenuItem("Paste Cell", KeyEvent.VK_Z);
			paste.setEnabled(false);
			paste.addActionListener(this);
			popup.add(paste);
			
			delete = new JMenuItem("Delete Cell", KeyEvent.VK_DELETE);
			delete.addActionListener(this);
			popup.add(delete);
			
			changeName = new JMenuItem("Assign Secondary Name", KeyEvent.VK_0);
			changeName.addActionListener(this);
			popup.add(changeName);
		
		//Right-Click Mouse Listener for Menu
			formTable.addMouseListener( new MouseAdapter()
			{
				public void mouseClicked( MouseEvent e )
				{
					if ( SwingUtilities.isRightMouseButton( e ))
					{
						p = e.getPoint();
						rowNumber = formTable.rowAtPoint( p );
						columnNumber = formTable.columnAtPoint(p);
						popup.show(e.getComponent(), e.getX(), e.getY());
					}
				}		    
			});
		
		//Labels
			lblvv = new JLabel("VALUE VIEW");
			lblvv.setForeground(formColors.noMouse);
			lblvv.addMouseListener(this);
			lblfv = new JLabel("FORMULA VIEW");
			lblfv.setForeground(formColors.noMouse);
			lblfv.addMouseListener(this);

		//MenuBar -- File
			file = new JMenu("File");
			
			//Save Sub Menu
				save = new JMenu("Save");
				
				saveXML = new JMenuItem("Save to XML");
				saveXML.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.ALT_MASK));
				saveXML.addActionListener(this);
				saveXML.setEnabled(true);
				save.add(saveXML);
				
				saveCOMP = new JMenuItem("Save to GZip");
				saveCOMP.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, ActionEvent.ALT_MASK));
				saveCOMP.addActionListener(this);
				saveCOMP.setEnabled(true);
				save.add(saveCOMP);
				
				saveENCRYPT = new JMenuItem("Save to Encrypted GZip");
				saveENCRYPT.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, ActionEvent.ALT_MASK));
				saveENCRYPT.addActionListener(this);
				saveENCRYPT.setEnabled(true);
				save.add(saveENCRYPT);
				
				saveCLOUD = new JMenuItem("Save to Database");
				saveCLOUD.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, ActionEvent.ALT_MASK));
				saveCLOUD.addActionListener(this);
				saveCLOUD.setEnabled(true);
				save.add(saveCLOUD);
				
			file.add(save);
			
			//Load Sub Menu
			load = new JMenu("Load");
				loadLocal = new JMenuItem("Load From Local", KeyEvent.VK_L);
				loadLocal.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.ALT_MASK));
				loadLocal.addActionListener(this);
				loadLocal.setEnabled(true);
				load.add(loadLocal);
				
				loadCLOUD = new JMenuItem("Load From Database", KeyEvent.VK_K);
				loadCLOUD.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_K, ActionEvent.ALT_MASK));
				loadCLOUD.addActionListener(this);
				loadCLOUD.setEnabled(true);
				load.add(loadCLOUD);
			
			file.add(load);
			
			deleteCLOUD = new JMenuItem("Delete From Database", KeyEvent.VK_D);
			deleteCLOUD.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, ActionEvent.ALT_MASK));
			deleteCLOUD.addActionListener(this);
			deleteCLOUD.setEnabled(true);
			file.add(deleteCLOUD);
			
			print = new JMenuItem("Print", KeyEvent.VK_P);
			print.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, ActionEvent.ALT_MASK));
			print.addActionListener(this);
			print.setEnabled(false);
			file.add(print);
			
			file.addSeparator();
			
			exit = new JMenuItem("Exit", KeyEvent.VK_Q);
			exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, ActionEvent.ALT_MASK));
			exit.addActionListener(this);
			file.add(exit);
		
		//MenuBar -- Window
			show = new JMenu("Window");
			
			moveFV = new JMenuItem("Give Formula View Precedence", KeyEvent.VK_1);
			moveFV.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
			moveFV.addActionListener(this);
			show.add(moveFV);
			moveFV.setEnabled(false);
			
			moveVV = new JMenuItem ("Give Value View Precedence", KeyEvent.VK_2);
			moveVV.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK));
			moveVV.addActionListener(this);
			show.add(moveVV);
			
			show.addSeparator();
			
			hideVV = new JMenuItem ("Show Only Formula View", KeyEvent.VK_3);
			hideVV.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_3, ActionEvent.ALT_MASK));
			hideVV.addActionListener(this);
			show.add(hideVV);
	
			hideFV = new JMenuItem ("Show Only Value View", KeyEvent.VK_4);
			hideFV.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_4, ActionEvent.ALT_MASK));
			hideFV.addActionListener(this);
			show.add(hideFV);
			
			show.addSeparator();
			
			equal = new JMenuItem ("Equal Size", KeyEvent.VK_E);
			equal.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.ALT_MASK));
			equal.addActionListener(this);
			show.add(equal);
	
			fullscreen = new JMenuItem("Full Screen", KeyEvent.VK_ENTER);
			fullscreen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, ActionEvent.ALT_MASK));
			fullscreen.addActionListener(this);
			show.add(fullscreen);
		
		//MenuBar -- Colors
			colors = new JMenu("Colors");
			
			lines = new JMenuItem ("Remove Shading", KeyEvent.VK_Y);
			lines.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, ActionEvent.ALT_MASK));
			lines.addActionListener(this);
			colors.add(lines);
			
			colors.addSeparator();
			
			defaultProfile = new JMenuItem ("Default Colors");
			defaultProfile.addActionListener(this);
			colors.add(defaultProfile);
			defaultProfile.setEnabled(false);
			
			consoleProfile = new JMenuItem ("Console Colors");
			consoleProfile.addActionListener(this);
			colors.add(consoleProfile);
			
			valentineProfile = new JMenuItem ("Shades of Red");
			valentineProfile.addActionListener(this);
			colors.add(valentineProfile);
	
			watermelonProfile = new JMenuItem ("Watermelon");
			watermelonProfile.addActionListener(this);
			colors.add(watermelonProfile);
			
			halloweenProfile= new JMenuItem ("Halloween");
			halloweenProfile.addActionListener(this);
			colors.add(halloweenProfile);
			
			//colors.addSeparator();
			
			coolestProfile = new JMenuItem ("Coolest Color Scheme Ever");
			coolestProfile.addActionListener(this);
			coolestProfile.setVisible(false);
			colors.add(coolestProfile);
			
			evenCooler = new JMenuItem ("Even Cooler Than The One Above!");
			evenCooler.addActionListener(this);
			evenCooler.setVisible(false);
			colors.add(evenCooler);
			
		//MenuBar -- Reset
			reset = new JMenu("Reset");
			
			clear = new JMenuItem("Clear SpreadSheet", KeyEvent.VK_C);
			clear.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.ALT_MASK));
			clear.addActionListener(this);
			reset.add(clear);
			
			resetNames = new JMenuItem("Reset Names and Clear Spreadsheet", KeyEvent.VK_DELETE);
			resetNames.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, ActionEvent.ALT_MASK));
			resetNames.addActionListener(this);
			reset.add(resetNames);
		
		//MenuBar
			menuBar = new JMenuBar();
			menuBar.add(file);
			menuBar.add(show);
			menuBar.add(colors);
			menuBar.add(reset);
			setJMenuBar(menuBar);

		//Bringing the two tables together
			valTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
			formTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		
		//Hard Coded Row Headers
		    ListModel lm = new AbstractListModel() {
		        String headers[] = {"0","1","2","3","4","5","6","7", "8", "9",
		        					"10","11","12","13","14","15","16","17", "18", "19",
		        					"20","21","22","23","24","25","26","27", "28", "29",
		        					"30","31","32","33","34","35","36","37", "38", "39",
		        					"40","41","42","43","44","45","46","47", "48", "49",
		        					"50","51","52","53","54","55","56","57", "58", "59",
		        					"60","61","62","63","64","65","66","67", "68", "69",
		        					"70","71","72","73","74","75","76","77", "78", "79",
		        					"80","81","82","83","84","85","86","87", "88", "89",
		        					"90","91","92","93","94","95","96","97", "98", "99"};
		        
		        public int getSize() { return headers.length; }
		        public Object getElementAt(int index) {
		          return headers[index];
		        }
		      };
		
		      JList rowHeader = new JList(lm);
		      rowHeader.setFixedCellWidth(50);
		      JList rowHeader2 = new JList(lm);
		      rowHeader2.setFixedCellWidth(50);
	    
		      rowHeader.setFixedCellHeight(valTable.getRowHeight());
		      rowHeader.setCellRenderer(new rowHeader(valTable));
	    
	    //Selects only the cell(s) that are directly clicked
			formTable.setRowSelectionAllowed(true);
			formTable.setColumnSelectionAllowed(true);
			valTable.setRowSelectionAllowed(true);
			valTable.setColumnSelectionAllowed(true);
		
		//Sets up default orientation of the tables with FormTable with Precedence
			JScrollPane jsp1 = new JScrollPane(valTable);
			jsp1.setRowHeaderView(rowHeader);
			
			//Label for ValTable
			valPanel.add(lblvv, BorderLayout.NORTH);
			valPanel.add(jsp1, BorderLayout.CENTER);
			pane.add(valPanel,BorderLayout.WEST);
			
		    rowHeader2.setFixedCellHeight(formTable.getRowHeight());
		    rowHeader2.setCellRenderer(new rowHeader(formTable));
			JScrollPane jsp2 = new JScrollPane(formTable);
			jsp2.setRowHeaderView(rowHeader2);
			
			//Label for FormTable
			formPanel.add(lblfv, BorderLayout.NORTH);
			formPanel.add(jsp2, BorderLayout.CENTER);
			pane.add(formPanel,BorderLayout.CENTER);		
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("SpreadSheet -- Group Manbearpig");
		setSize(1000,750);
		
		Random r = new Random();
		x = r.nextInt(100);
		y = r.nextInt(100);
		
		String wCell = formTable.getColumnName(x) + y;
		nameMap.put("Waldo",wCell);
		altNameMap.put(wCell, "Waldo");
		
		try
		{
			Tools.addVariable("Waldo:" + wCell);
		} 
		catch (VariableAssignmentException e1) 
		{
			System.out.println("Waldo was not placed. :(");
		}
		
		if(!loggedIn)
		{
			saveENCRYPT.setEnabled(false);
			saveCLOUD.setEnabled(false);
			loadCLOUD.setEnabled(false);
			deleteCLOUD.setEnabled(false);
		}
	}
	
	/**
	 * Revalidates and repaints both tables
	 * 
	 * @return VOID
	 */
	public void updateTables(){
		valTable.revalidate();
		valTable.repaint();
		formTable.revalidate();
		formTable.repaint();
	}
	/**
	 * Clears all of the Hash Maps, and then adds all of the original Cell names
	 * so that they cannot be used more than once.
	 * 
	 * @return VOID
	 */
	public void resetNameHash()
	{
		nameMap = new HashMap<String,String>();
		altNameMap = new HashMap<String,String>();
		Tools.variableTable = new HashMap<String,String>();
		
		// Add cell names To nameMap so they cannot be used as names
			for(int i = 0; i < 100; i++){
				for(int j = 0; j < 100; j++)
				{
					String cell = formTable.getColumnName(i) + j;
					nameMap.put(cell, null);
				}
			}
	}
	/**
	 * Moves the ValueTable to the West end of the BorderLayout
	 * Is used to give FormTable precedence
	 * 
	 * @return VOID
	 */
	public void moveValueViewWest()
	{
		valPanel.setVisible(false);
		pane.add(valPanel,BorderLayout.WEST);
		valPanel.setVisible(true);
	}
	/**
	 * Moves the ValueTable to the Center of the BorderLayout
	 * Is used to give ValueTable precedence
	 * 
	 * @return VOID
	 */
	public void moveValueViewCenter()
	{
		middle.setVisible(false);
		valPanel.setVisible(false);
		pane.add(valPanel,BorderLayout.CENTER);
		valPanel.setVisible(true);
	}
	/**
	 * Moves the FormulaTable to the East end of the BorderLayout
	 * Is used to give ValueTable precedence
	 * 
	 * @return VOID
	 */
	public void moveFormulaViewEast()
	{
		formPanel.setVisible(false);
		pane.add(formPanel,BorderLayout.EAST);
		formPanel.setVisible(true);
	}
	/**
	 * Moves the FormTable to the Center of the BorderLayout
	 * Is used to give FormTable precedence
	 * 
	 * @return VOID
	 */
	public void moveFormulaViewCenter()
	{
		middle.setVisible(false);
		formPanel.setVisible(false);
		pane.add(formPanel,BorderLayout.CENTER);
		formPanel.setVisible(true);
	}
	/**
	 * Moves Both Tables to a GridLayout in the Center Pane
	 * Is used to give Equal Sizes for both Tables
	 * 
	 * @return VOID
	 */
	public void moveToEqualSize()
	{
		formPanel.setVisible(false);
		valPanel.setVisible(false);
		middle.add(valPanel);
		middle.add(formPanel);
		pane.add(middle, BorderLayout.CENTER);
		middle.setVisible(true);
		formPanel.setVisible(true);
		valPanel.setVisible(true);
	}
	/**
	 * Disables the View of FormTable
	 * 
	 * @return VOID
	 */
	public void showOnlyValueView()
	{
		middle.setVisible(false);
		formPanel.setVisible(false);
		valPanel.setVisible(false);
		pane.add(valPanel, BorderLayout.CENTER);
		valPanel.setVisible(true);
	}
	/**
	 * Disables the View of ValTable
	 * 
	 * @return VOID
	 */
	public void showOnlyFormulaView()
	{
		middle.setVisible(false);
		formPanel.setVisible(false);
		valPanel.setVisible(false);
		pane.add(formPanel, BorderLayout.CENTER);
		formPanel.setVisible(true);
	}
	/**
	 * Performs the various actions of the MenuButtons, in both the
	 * MenuBar as well as the popup Menu
	 * 
	 * @param e	Event Performed, tied to an item with an ActionListener
	 * attached to it
	 * 
	 * @return VOID
	 */
	public void actionPerformed( ActionEvent e)
    {
		Object source = (e.getSource());

		
		formFull = false;
		valFull = false;
		if(source == exit)
		{
			int choice = JOptionPane.showConfirmDialog(null, "Would you like to save before you close?");
			if(choice == JOptionPane.YES_OPTION)
			{
				String fileName = null;
				String filePath = null;
				String extension = "";
				JFileChooser chooser = new JFileChooser();
				chooser.setCurrentDirectory (new File ("."));
				int returnVal = chooser.showSaveDialog(this);
				if(returnVal == JFileChooser.APPROVE_OPTION) {
				      fileName = chooser.getSelectedFile().getName();
				      filePath = chooser.getSelectedFile().toString();
				      if(fileName.lastIndexOf(".") != -1){
				    	  extension = fileName.substring(fileName.lastIndexOf("."), fileName.length());
				      }
				}
				if(fileName == null){
					// Do Nothing
				}
				else if(invalidFileName(filePath,fileName)){
					JOptionPane.showMessageDialog(null, "Invalid File Name");
				}
				else if(!(extension.equals(".xml"))){
					JOptionPane.showMessageDialog(null, "File Must Have \".xml\" Extension");
				}
				else
				{
					boolean success = saveXML(filePath);
					if(success){
						JOptionPane.showMessageDialog(null,"The file: " + fileName + " has been successfully created.");
						setFrameTitle(fileName, this);
					}
					else{
						JOptionPane.showMessageDialog(null, "Error Saving File");
					}
				}
				System.exit(0);
			}
			else if(choice == JOptionPane.NO_OPTION)
			{
				System.exit(0);
			}
		}
		else if(source == clear)
		{	
			if(formTable.getCellEditor() != null){
				formTable.getCellEditor().cancelCellEditing();
			}
			formTable.clearSelection();
			tm2.initiateValues();
		}
		else if(source == resetNames)
		{
			clearEverything();
		}
		else if(source == moveVV)
		{
			moveValueViewCenter();
			moveFormulaViewEast();
			
			moveVV.setEnabled(false);
			moveFV.setEnabled(true);
			hideVV.setEnabled(true);
			hideFV.setEnabled(true);
			equal.setEnabled(true);
			
		}
		else if(source == moveFV)
		{
			moveFormulaViewCenter();
			moveValueViewWest();
			
			moveVV.setEnabled(true);
			moveFV.setEnabled(false);
			hideVV.setEnabled(true);
			hideFV.setEnabled(true);
			equal.setEnabled(true);
		}
		else if(source == hideVV)
		{
			showOnlyFormulaView();
			
			moveVV.setEnabled(true);
			moveFV.setEnabled(true);
			hideVV.setEnabled(false);
			hideFV.setEnabled(true);
			equal.setEnabled(true);
			formFull = true;
		}
		else if(source == hideFV)
		{
			showOnlyValueView(); 
			
			moveVV.setEnabled(true);
			moveFV.setEnabled(true);
			hideVV.setEnabled(true);
			hideFV.setEnabled(false);
			equal.setEnabled(true);
			valFull = true;
		}
		else if(source == equal)
		{
			moveToEqualSize();
			
			moveVV.setEnabled(true);
			moveFV.setEnabled(true);
			hideVV.setEnabled(true);
			hideFV.setEnabled(true);
			equal.setEnabled(false);
		}
		else if(source == fullscreen)
			this.setExtendedState(Frame.MAXIMIZED_BOTH);
		else if (source == print)
			;//does nothing still.
		else if (((AbstractButton) source).getText() == "Remove Shading")
		{
			formColors.isShaded = false;
			((AbstractButton) source).setText("Add Shading");
		}
		else if (((AbstractButton) source).getText() == "Add Shading")
		{
			formColors.isShaded = true;
			((AbstractButton) source).setText("Remove Shading");
		}
		else if(source == defaultProfile)
		{
			formColors.setDefaultProfile();
			defaultProfile.setEnabled(false);
			consoleProfile.setEnabled(true);
			valentineProfile.setEnabled(true);
			watermelonProfile.setEnabled(true);
			halloweenProfile.setEnabled(true);
			lblvv.setForeground(formColors.noMouse);
			lblfv.setForeground(formColors.noMouse);
			formTable.setGridColor(formColors.grid);
			valTable.setGridColor(formColors.grid);
		}
		else if(source == consoleProfile)
		{
			formColors.setConsoleProfile();
			defaultProfile.setEnabled(true);
			consoleProfile.setEnabled(false);
			valentineProfile.setEnabled(true);
			watermelonProfile.setEnabled(true);
			halloweenProfile.setEnabled(true);
			lblvv.setForeground(formColors.noMouse);
			lblfv.setForeground(formColors.noMouse);
			formTable.setGridColor(formColors.grid);
			valTable.setGridColor(formColors.grid);
		}
		else if(source == valentineProfile)
		{
			formColors.setValentinesProfile();
			defaultProfile.setEnabled(true);
			consoleProfile.setEnabled(true);
			valentineProfile.setEnabled(false);
			watermelonProfile.setEnabled(true);
			halloweenProfile.setEnabled(true);
			lblvv.setForeground(formColors.noMouse);
			lblfv.setForeground(formColors.noMouse);
			formTable.setGridColor(formColors.grid);
			valTable.setGridColor(formColors.grid);
		}
		else if(source == watermelonProfile)
		{
			formColors.setWatermelonProfile();
			defaultProfile.setEnabled(true);
			consoleProfile.setEnabled(true);
			valentineProfile.setEnabled(true);
			watermelonProfile.setEnabled(false);
			halloweenProfile.setEnabled(true);
			lblvv.setForeground(formColors.noMouse);
			lblfv.setForeground(formColors.noMouse);
			formTable.setGridColor(formColors.grid);
			valTable.setGridColor(formColors.grid);
		}
		else if(source == halloweenProfile)
		{
			formColors.setHalloweenProfile();
			defaultProfile.setEnabled(true);
			consoleProfile.setEnabled(true);
			valentineProfile.setEnabled(true);
			watermelonProfile.setEnabled(true);
			halloweenProfile.setEnabled(false);
			lblvv.setForeground(formColors.noMouse);
			lblfv.setForeground(formColors.noMouse);
			formTable.setGridColor(formColors.grid);
			valTable.setGridColor(formColors.grid);
		}
		else if(source == saveXML)
		{
			String fileName = null;
			String filePath = null;
			String extension = "";
			JFileChooser chooser = new JFileChooser();
			chooser.setCurrentDirectory (new File ("."));
			int returnVal = chooser.showSaveDialog(this);
			if(returnVal == JFileChooser.APPROVE_OPTION) {
			      fileName = chooser.getSelectedFile().getName();
			      filePath = chooser.getSelectedFile().toString();
			      if(fileName.lastIndexOf(".") != -1){
			    	  extension = fileName.substring(fileName.lastIndexOf("."), fileName.length());
			      }
			}
			if(fileName == null){
				// Do Nothing
			}
			else if(invalidFileName(filePath,fileName)){
				JOptionPane.showMessageDialog(null, "Invalid File Name");
			}
			else if(!(extension.equals(".xml"))){
				JOptionPane.showMessageDialog(null, "File Must Have \".xml\" Extension");
			}
			else
			{
				boolean success = saveXML(filePath);
				if(success){
					JOptionPane.showMessageDialog(null,"The file: " + fileName + " has been successfully created.");
					setFrameTitle(fileName, this);
				}
				else{
					JOptionPane.showMessageDialog(null, "Error Saving File");
				}
			}
		}
		else if(source == saveCOMP){
			String fileName = null;
			String filePath = null;
			String extension = "";
			JFileChooser chooser = new JFileChooser();
			chooser.setCurrentDirectory (new File ("."));
			int returnVal = chooser.showSaveDialog(this);
			if(returnVal == JFileChooser.APPROVE_OPTION) {
			      fileName = chooser.getSelectedFile().getName();
			      filePath = chooser.getSelectedFile().toString();
			      if(fileName.lastIndexOf(".") != -1){
			    	  extension = fileName.substring(fileName.lastIndexOf("."), fileName.length());
			      }
			}
			if(fileName == null){
				// Do Nothing
			}
			else if(invalidFileName(filePath,fileName)){
				JOptionPane.showMessageDialog(null, "Invalid File Name");
			}
			else if(!(extension.equals(".gz"))){
				JOptionPane.showMessageDialog(null, "File Must Have \".gz\" Extension");
			}
			else
			{
				boolean success = saveCompressed(filePath);
				if(success){
					JOptionPane.showMessageDialog(null,"The file: " + fileName + " has been successfully created.");
					setFrameTitle(fileName, this);
				}
				else{
					JOptionPane.showMessageDialog(null, "Error Saving File");
				}
			}
		}
		else if(source == saveENCRYPT)
		{
			saveEncrypted();
		}
		else if (source == saveCLOUD)
		{
			saveToCloud();	
		}
		else if (source == loadLocal)
		{
			loadLocally();
		}
		else if (source == loadCLOUD)
		{
			loadCLOUD();
		}
		else if (source == deleteCLOUD)
		{
			deleteCLOUD();
		}
		else if (source == copy)
		{
			copy(rowNumber,columnNumber);
		}
		else if (source == cut)
		{
			cut(rowNumber,columnNumber);
		}
		else if (source == paste)
		{
			paste(rowNumber,columnNumber);
		}
		else if (source == delete)
		{
			delete();
		}
		else if (source == changeName)
		{
				// get the row index that contains that coordinate
				int rowNumber = formTable.rowAtPoint( p );
				int columnNumber = formTable.columnAtPoint(p);
				
				String cell = formTable.getColumnName(columnNumber) + rowNumber;			
				
				if(nameMap.containsValue(cell))
				{
					JOptionPane.showMessageDialog(null,
						    cell + " already has a secondary name.",
						    "Name Cell", JOptionPane.WARNING_MESSAGE);
				}
				else
				{
					String name = JOptionPane.showInputDialog(null,
							  "Enter an alphanumeric secondary name for " + cell + ":",
							  "Name Cell " + cell,
							  JOptionPane.PLAIN_MESSAGE);
					// If name isn't null or empty and doesn't contain spaces set the name
					if(!(name == null || name.split(" ").length != 1 || name.trim().equals(""))){
						// Show message if name was already used
						if(nameMap.containsKey(name.trim())){
							if(nameMap.get(name.trim()) == null ){
								JOptionPane.showMessageDialog(null,
										"Cannot use a cell name as a secondary name",
										"Name Cell",
										JOptionPane.WARNING_MESSAGE);
							}
							else{
								JOptionPane.showMessageDialog(null,
										name.trim() + " is already set to " + nameMap.get(name.trim()),
										"Name Cell",
										JOptionPane.WARNING_MESSAGE);
							}
						}
						else if(name.charAt(0) >= '0' && name.charAt(0) <= '9')
							JOptionPane.showMessageDialog(null,
								    name.trim() + " is not allowed, a Secondary Name must start with a letter.",
								    "Name Cell",
								    JOptionPane.WARNING_MESSAGE);
						else
						{
							nameMap.put(name.trim(), cell);
							altNameMap.put(cell, name.trim());
							try {
								Tools.addVariable(name.trim() + ": " + cell);
								
							} catch (VariableAssignmentException e1) {
								e1.printStackTrace();
							}
						}
					}
					else{
						// Show message if name wasn't set
						JOptionPane.showMessageDialog(null,
							    "Name wasn't set for " + cell,
							    "Name Cell",
							    JOptionPane.WARNING_MESSAGE);
					}
				}

					
		}
		else if(source == confirm)
		{
			ArrayList<String> selected = new ArrayList<String>();
			for(int i = 0; i < users.size(); i++)
			{
				if(userCheck.get(i).isSelected())
					selected.add(users.get(i));
			}
			
			userFrame.setVisible(false);
			
			String fileName = null;
			
			
			fileName = JOptionPane.showInputDialog("Enter Filename followed by .gz");
			String extension = fileName.substring(fileName.lastIndexOf('.'));
			
			String temp = User.currentUser;
			if(fileName == null){
				// Do Nothing
			}

			else if(!(extension.equals(".gz"))){
				JOptionPane.showMessageDialog(null, "File Must Have \".gz\" Extension");
			}
			else if(fileName.length() > 20)
			{
				JOptionPane.showMessageDialog(null, "File Name is too long, please choose another.");
			}
			else
			{
				boolean success = false;

				if(DatabaseUtil.fileInDB(fileName)){
					if(DatabaseUtil.isFileOwner(User.currentUser, fileName)){
						for(int i = 0; i < selected.size(); i++)
						{
								User.currentUser = selected.get(i);
								DatabaseUtil.getPublicKey(User.currentUser);
								if(DatabaseUtil.canRetrieveFile(User.currentUser, fileName)){
									success = SpreadToXML.save(formTable,altNameMap, true, generatePasskey(), "spreadsheet.temp");
									Compress.compressFile(fileName + ".temp");
									Compress.deleteFile("spreadsheet.temp");
									DatabaseUtil.overWriteFile(User.currentUser, fileName);
									Compress.deleteFile(fileName + ".temp");
								}
								else{
									success = SpreadToXML.save(formTable,altNameMap, true, generatePasskey(), "spreadsheet.temp");
									Compress.compressFile(fileName + ".temp");
									Compress.deleteFile("spreadsheet.temp");
									DatabaseUtil.saveFile(User.currentUser, fileName);
									Compress.deleteFile(fileName + ".temp");
								}
						}

					}
					else{
						JOptionPane.showMessageDialog(null, "Sorry you are not the owner of this file.");
					}
				}
				else{
					DatabaseUtil.setFileOwner(User.currentUser, fileName);
					for(int i = 0; i < selected.size(); i++)
					{
							User.currentUser = selected.get(i);
							DatabaseUtil.getPublicKey(User.currentUser);
							if(DatabaseUtil.canRetrieveFile(User.currentUser, fileName)){
								success = SpreadToXML.save(formTable,altNameMap, true, generatePasskey(), "spreadsheet.temp");
								Compress.compressFile(fileName + ".temp");
								Compress.deleteFile("spreadsheet.temp");
								DatabaseUtil.overWriteFile(User.currentUser, fileName);
								Compress.deleteFile(fileName + ".temp");
							}
							else{
								success = SpreadToXML.save(formTable,altNameMap, true, generatePasskey(), "spreadsheet.temp");
								Compress.compressFile(fileName + ".temp");
								Compress.deleteFile("spreadsheet.temp");
								DatabaseUtil.saveFile(User.currentUser, fileName);
								Compress.deleteFile(fileName + ".temp");
							}
					}

				}

				if(success)
				{
					JOptionPane.showMessageDialog(null,"The file: " + fileName + " has been successfully created.");
					setFrameTitle(fileName, this);
				}
				else
					JOptionPane.showMessageDialog(null, "Error Saving File");
				
				User.currentUser = temp;
			}
		}
		else if(source == saveCancel)
			userFrame.setVisible(false);
		else if(source == loadCancel)
			loadFrame.setVisible(false);
		updateTables();
    }
	/**
	 * A pseudo copy method, can only do ONE cell and saves it as a string
	 * 
	 * @return VOID
	 */
	public static void copy(int row,int column)
	{
		clipboard = formTable.getValueAt(row, column).toString();
		paste.setEnabled(true);
	}
	/**
	 * A pseudo cut method, can only do ONE cell and saves it as a string
	 * Also it deletes the contents of the cell
	 * 
	 * @return VOID
	 */
	public static void cut(int row,int column)
	{
		clipboard = formTable.getValueAt(row, column).toString();
		paste.setEnabled(true);
		formTable.setValueAt("",row, column);
	}
	/**
	 * A pseudo paste method, can only do ONE cell and sets the Cell with a copied string
	 * 
	 * @return VOID
	 */
	public static void paste(int row,int column)
	{
		if(!clipboard.equals(null))
		{
			formTable.setValueAt(clipboard,row, column);
		}
	}
	/**
	 * Deletes the contents of the Cell
	 * 
	 * @return VOID
	 */
	public static void delete()
	{
		if(formTable.getCellEditor() != null){
			formTable.getCellEditor().cancelCellEditing();
		}
		tm2.setValueAt("",formTable.getSelectedRow(), formTable.getSelectedColumn());
	}
	/**
	 * Creates a new Frame
	 * 
	 * @param args Original input is not necessary
	 * @return VOID
	 */
	public static void main(String[] args){
		String pass = "";
		if(args.length != 0 && args[0]!=null){
			pass = args[0];
		}
		dbPassword = pass;
		loggedIn = userInit();
		new Frame().setVisible(true);
	}
	/**
	 * Implements the Mouse listener method, If the JLabel for the table is
	 * clicked, then it will show only that table, if only that table is shown
	 * and the JLabel is clicked, it will switch to the other Table automatically
	 * 
	 * @param e	The mouse Click event
	 * @return VOID
	 */
	public void mouseClicked(MouseEvent e) {
				JLabel source = (JLabel)(e.getSource());
				Boolean success = false;
				if(source == lblvv)
				{
					if(valFull == true)
					{
						formFull = true;
						valFull = false;
						showOnlyFormulaView();
						
						moveVV.setEnabled(true);
						moveFV.setEnabled(true);
						hideVV.setEnabled(false);
						hideFV.setEnabled(true);
						equal.setEnabled(true);
					}
					else
					{
						valFull = true;
						showOnlyValueView(); 
					
						moveVV.setEnabled(true);
						moveFV.setEnabled(true);
						hideVV.setEnabled(true);
						hideFV.setEnabled(false);
						equal.setEnabled(true);
					}
				}
				else if(source == lblfv)
				{
					if(formFull == true)
					{
						formFull = false;
						valFull = true;
						showOnlyValueView(); 
						
						moveVV.setEnabled(true);
						moveFV.setEnabled(true);
						hideVV.setEnabled(true);
						hideFV.setEnabled(false);
						equal.setEnabled(true);
					}
					else
					{
						formFull = true;
					showOnlyFormulaView();
					
					moveVV.setEnabled(true);
					moveFV.setEnabled(true);
					hideVV.setEnabled(false);
					hideFV.setEnabled(true);
					equal.setEnabled(true);
					}
				}
				else
				{
					for(int i = 0; i < fileLabels.size(); i++)
					{
						if(source==fileLabels.get(i))
						{
							fileLabels.get(i).setForeground(formColors.noMouse);
							loadFrame.setVisible(false);
							
							if(!DatabaseUtil.isFileOwner(User.currentUser, fileLabels.get(i).getText()))
							{
								formTable.setEnabled(false);
								valTable.setEnabled(false);
								formTable.setCellSelectionEnabled(false);
								valTable.setCellSelectionEnabled(false);
								delete.setEnabled(false);
								cut.setEnabled(false);
								copy.setEnabled(false);
								paste.setEnabled(false);
								changeName.setEnabled(false);
							}
							else
							{
								formTable.setEnabled(true);
								valTable.setEnabled(true);
								formTable.setCellSelectionEnabled(true);
								valTable.setCellSelectionEnabled(true);
								delete.setEnabled(true);
								cut.setEnabled(true);
								copy.setEnabled(true);
								paste.setEnabled(true);
								changeName.setEnabled(true);
							}
							this.setTitle(fileLabels.get(i).getText());
							
							DatabaseUtil.retrieveFile(User.currentUser, fileLabels.get(i).getText());
							Compress.decompressFile("blob_" + fileLabels.get(i).getText());
							
							Compress.deleteFile("blob_" + fileLabels.get(i).getText());
							
							try {
								XMLToSpread.load("spreadsheet.temp");
							} 
							
							catch (InvalidKeyException e1) {} 
							catch (IllegalBlockSizeException e1) {} 
							catch (BadPaddingException e1) {} 
							catch (NoSuchAlgorithmException e1) {}
							catch (NoSuchPaddingException e1) {}
							catch (InvalidKeySpecException e1) {} 
							catch (IOException e1) {}
							
							Compress.deleteFile("spreadsheet.temp");
						}
					}
					fileLabels.removeAll(fileLabels);//may not need
					loadFrame.setVisible(false);
					for(int i = 0; i < deleteLabels.size(); i++)
					{
						if(source==deleteLabels.get(i))
						{
							success = DatabaseUtil.deleteFile(deleteLabels.get(i).getText());
							success = DatabaseUtil.deleteFileFromOwnerTable(deleteLabels.get(i).getText());
							if(success)
								JOptionPane.showMessageDialog(null,
										"The File \"" + deleteLabels.get(i).getText() + "\" was successfully deleted."
										, "Successful Deletion", 0);
						}
					}
				}

	}
	
	
	/**
	 * Implements another part of the MouseListener, changes the color of the
	 * JLabel if mouse hovers over the label, the color is determined by the
	 * profile in formColors.java as mouseHover
	 * 
	 * @return VOID
	 */
	public void mouseEntered(MouseEvent e) {
		JLabel source = (JLabel)(e.getSource());
		if(source == lblvv)
			lblvv.setForeground(formColors.mouseHover);
		else if(source == lblfv)
			lblfv.setForeground(formColors.mouseHover);
		else if(fileLabels.size() > 0)
		{
			for(int i = 0; i < fileLabels.size(); i++)
			{
				if(source==fileLabels.get(i))
					fileLabels.get(i).setForeground(formColors.mouseHover);
			}
		}
		else if(deleteLabels.size() > 0)
		{
			for(int i = 0; i < deleteLabels.size(); i++)
			{
				if(source==deleteLabels.get(i))
					deleteLabels.get(i).setForeground(formColors.mouseHover);
			}
		}
	}
	/**
	 * Implements another part of the MouseListener, changes the color of the
	 * JLabel if mouse exits from over the label, the color is determined by the
	 * profile in formColors.java as noMouse
	 * 
	 * @return VOID
	 */
	public void mouseExited(MouseEvent e) {
		JLabel source = (JLabel)(e.getSource());
		if(source == lblvv)
			lblvv.setForeground(formColors.noMouse);
		else if(source == lblfv)
			lblfv.setForeground(formColors.noMouse);
		else
		{
			for(int i = 0; i < fileLabels.size(); i++)
			{
				if(source==fileLabels.get(i))
					fileLabels.get(i).setForeground(formColors.noMouse);
			}
			for(int i = 0; i < deleteLabels.size(); i++)
			{
				if(source==deleteLabels.get(i))
					deleteLabels.get(i).setForeground(formColors.noMouse);
			}
		}
	}
	/**
	 * Implements another part of the MouseListener, changes the color of the
	 * JLabel if mouse clicks the label, the color is determined by the
	 * profile in formColors.java as mouseClicked
	 * 
	 * @return VOID
	 */
	public void mousePressed(MouseEvent e) {
		JLabel source = (JLabel)(e.getSource());
		
		if(source == lblvv)
			lblvv.setForeground(formColors.mouseClicked);
		else if(source == lblfv)
			lblfv.setForeground(formColors.mouseClicked);
		else
		{
			for(int i = 0; i < fileLabels.size(); i++)
			{
				if(source==fileLabels.get(i))
					fileLabels.get(i).setForeground(formColors.mouseClicked);
			}
			for(int i = 0; i < deleteLabels.size(); i++)
			{
				if(source==deleteLabels.get(i))
					deleteLabels.get(i).setForeground(formColors.mouseClicked);
			}
		}
	}
	/**
	 * Implements another part of the MouseListener, changes the color of the
	 * JLabel if mouse releases the click from over the label, the color is determined by the
	 * profile in formColors.java as noMouse
	 * 
	 * @return VOID
	 */
	public void mouseReleased(MouseEvent e) {
		JLabel source = (JLabel)(e.getSource());
		if(source == lblvv)
			lblvv.setForeground(formColors.noMouse);
		else if(source == lblfv)
			lblfv.setForeground(formColors.noMouse);
	}
	/**
	 * Sets if there has been an error detected by ValTable.java
	 * CellRenderer will detect this and change the color in valTable
	 * 
	 * @return VOID
	 */
	public static void setErrorTrue(int row)
	{
		err = true;
		errorRow = row;
	}
	/**
	 * CellRenderer resets the error flag so that it can check to see if the error still persists
	 * 
	 * @return VOID
	 */
	public static void setErrorFalse(int row)
	{
		err = false;
		errorRow = row;
	}
	/**
	 * setFrameTitle takes in the title of the file saved/loaded and sets the frame title to match it.
	 * 
	 * @param title file name to be set to the title
	 * @return VOID
	 */
	public static void setFrameTitle(String title,Frame f)
	{
		f.setTitle("\"" + title + "\"");
	}
	//will move to new file...
	/**
	 * Tests whether the given string is an invalid file name.
	 * 
	 * @param filename
	 * @return true if the filename is invalid
	 */
	public boolean invalidFileName(String filePath, String fileName){
		if(filePath.contains("\\")|| 
				filePath.contains("?")||filePath.contains("%")||filePath.contains("*")||
				filePath.contains(":")||filePath.contains("|")||filePath.contains("\"")||
				filePath.contains("&")||filePath.contains("*")||filePath.contains("(")||
				filePath.contains("<")||filePath.contains(">"))
		{
			return true;
		}
		
		if(fileName.contains("\\")|| fileName.contains("/")|| 
				fileName.contains("?")||fileName.contains("%")||fileName.contains("*")||
				fileName.contains(":")||fileName.contains("|")||fileName.contains("\"")||
				fileName.contains("&")||fileName.contains("*")||fileName.contains("(")||
				fileName.contains("<")||fileName.contains(">"))
		{
			return true;
		}
		
		if(fileName.length() > 20){
			return true;
		}
		
		if(fileName.indexOf(".") == 0 || fileName.indexOf("-") == 0){
			return true;
		}
		
		return false;

	}
	
	/**
	 * Save spread sheet to an XML file with given file name.
	 * @param fileName
	 * @return true if saved successfully
	 */
	public boolean saveXML(String fileName){
		
		return SpreadToXML.save(formTable,altNameMap, false, "-1", fileName);
	}
	
	/**
	 * Save spreadsheet to an compressed XML file with given file name.
	 * @param fileName
	 * @return true if saved successfully
	 */
	public boolean saveCompressed(String fileName){
		
		boolean success = SpreadToXML.save(formTable,altNameMap, false, "-1", "spreadsheet.temp");
		if(success){
			Compress.compressFile(fileName);
			Compress.deleteFile("spreadsheet.temp");
			return true;
		}
		else{
			return false;
		}
	}
	
	
	public static boolean userInit(){
		if(canConnectToDB()){
			if(User.login()){
				if(! new File(User.currentUser+".pub").exists() || !new File(User.currentUser+".pri").exists()){
					JOptionPane.showMessageDialog(null, "Couldn't find your key files."
							+ "\nStarting Spreadsheet in Local Only Mode.");
					return false;
				}
			}
			else{
				JOptionPane.showMessageDialog(null, "Couldn't login, check your username."
						+ "\nStarting Spreadsheet in Local Only Mode.");
				return false;
			}
		}
		else{
			JOptionPane.showMessageDialog(null, "Couldn't Connect To Database, Check db.dat file."
					+ "\nStarting Spreadsheet in Local Only Mode.");
			return false;
		}
		return true;
	}
	
	
	public static boolean canConnectToDB(){
		
		DatabaseUtil.setDBPassword(dbPassword);
		return DatabaseUtil.canConnect();

	}
	/**
	 * Generates a random letter passkey using lowercase and uppercase characters
	 * 
	 * @return passkey random letter passkey
	 */
	public String generatePasskey()
	{
		String passkey = "";
		char character;
		Random gen = new Random();
		//Makes a random string to use as a password
		for(int i = 0; i < 15; i++)
		{
			//Flip a coin...uppercase or lowercase characters
			if(gen.nextInt(2) == 0)
			{
				character = (char)(gen.nextInt(10) + 65);
				passkey = passkey + character;
			}
			else
			{
				character = (char)(gen.nextInt(10) + 97);
				passkey = passkey + character;
			}
		}
		return passkey;
	}
	/**
	 * Save spreadsheet to a compressed XML file with given file name encrypted
	 * with a random password
	 * 
	 * @return void
	 */
	public void saveEncrypted(){
		String passkey = generatePasskey();
		
		String fileName = null;
		String extension = "";
		JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory (new File ("."));
		int returnVal = chooser.showSaveDialog(this);
		if(returnVal == JFileChooser.APPROVE_OPTION) {
		      fileName = chooser.getSelectedFile().getName();
		      if(fileName.lastIndexOf(".") != -1){
		    	  extension = fileName.substring(fileName.lastIndexOf("."), fileName.length());
		      }
		}
		if(fileName == null){
			// Do Nothing
		}
		//else if(invalidFileName(filePath,fileName)){
	//		JOptionPane.showMessageDialog(null, "Invalid File Name");
	//	}
		else if(!(extension.equals(".gz"))){
			JOptionPane.showMessageDialog(null, "File Must Have \".gz\" Extension");
		}
		else
		{
			boolean success = SpreadToXML.save(formTable,altNameMap, true, passkey, "spreadsheet.temp");
			if(success){
				Compress.compressFile(fileName);
				Compress.deleteFile("spreadsheet.temp");
				JOptionPane.showMessageDialog(null,"The file: " + fileName + " has been successfully created.");
				setFrameTitle(fileName, this);
			}
			else{
				JOptionPane.showMessageDialog(null, "Error Saving File");
			}

		}
		
	}
	/**
	 * Save Spreadsheet to blob in a Database
	 * 
	 * @return void
	 */
	public void saveToCloud()
	{
		users = DatabaseUtil.getAllUsers();
		userCheck = new ArrayList<JCheckBox>();
		userFrame = new JDialog((JFrame) null, "Users In Database", true);

		confirm = new JButton("Confirm and Send");
		saveCancel = new JButton("Cancel");

		confirm.addActionListener(this);
		saveCancel.addActionListener(this);
		
		userFrame.setSize(200,users.size()*50);
		userFrame.toFront();
		userFrame.setResizable(false);

		userFrame.setLayout(new GridLayout((users.size()+2),1));
		for(int i = 0; i < users.size(); i++)
		{
			userCheck.add(new JCheckBox(users.get(i)));
			
			if(users.get(i).equals(User.currentUser))
			{
				userCheck.get(i).setEnabled(false);
				userCheck.get(i).setToolTipText("This is you...");
				userCheck.get(i).setSelected(true);
			}
			
			userFrame.add(userCheck.get(i));	
		}
	
		userFrame.add(confirm);
		userFrame.add(saveCancel);
		userFrame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		userFrame.setVisible(true);
	}
	

	/**
	 * Loads file from local content
	 * 
	 * @return void
	 */
	public void loadLocally()
	{	
		saveFirst();
		if(cancelAction)
		{
			cancelAction = false;
			clearEverything();
			
			//In case you loaded from a cloud first
				formTable.setEnabled(true);
				valTable.setEnabled(true);
				formTable.setCellSelectionEnabled(true);
				valTable.setCellSelectionEnabled(true);
				delete.setEnabled(true);
				cut.setEnabled(true);
				copy.setEnabled(true);
				paste.setEnabled(true);
				changeName.setEnabled(true);
			
			String fileName = null;
			String filePath = null;
			JFileChooser chooser = new JFileChooser();
			chooser.setCurrentDirectory (new File ("."));
			int returnVal = chooser.showOpenDialog(this);
			if(returnVal == JFileChooser.APPROVE_OPTION) {
					fileName = chooser.getSelectedFile().getName();
					filePath = chooser.getSelectedFile().toString();
			}
	
			if(fileName == null){
				//Do Nothing, file not chosen
			}
			else if(fileName.substring(fileName.lastIndexOf(".")).equals(".gz")){
				formTable.clearSelection();
				tm2.initiateValues();
				resetNameHash();
				
				//file = file.substring(0, file.lastIndexOf("."));
				Compress.decompressFile(filePath);
				try 
				{
					if(! XMLToSpread.load("spreadsheet.temp"))
					{
						JOptionPane.showMessageDialog(null,"The file: " + fileName + " wasn't successfully loaded.");
					}
				} 
				catch (InvalidKeyException e1) 
				{
					JOptionPane.showMessageDialog(null, "Sorry, you have entered an invalid key.");
				} 
				catch (HeadlessException e1) {} 
				catch (IllegalBlockSizeException e1) {} 
				catch (BadPaddingException e1) {} 
				catch (NoSuchAlgorithmException e1) {} 
				catch (NoSuchPaddingException e1) {} 
				catch (IOException e1) {} 
				catch (InvalidKeySpecException e1) {} 
	
				setFrameTitle(fileName, this);
				Compress.deleteFile("spreadsheet.temp");
			}
			else{
	
				formTable.clearSelection();
				tm2.initiateValues();
				resetNameHash();
				
				try 
				{
					if(! XMLToSpread.load(filePath))
					{
						JOptionPane.showMessageDialog(null,"The file: " + fileName + " wasn't successfully loaded.");
					}
				}
				catch (InvalidKeyException e1) 
				{
					JOptionPane.showMessageDialog(null, "Sorry, you have entered an invalid key.");
				} 
				catch (HeadlessException e1) {} 
				catch (IllegalBlockSizeException e1) {} 
				catch (BadPaddingException e1) {} 
				catch (NoSuchAlgorithmException e1) {} 
				catch (NoSuchPaddingException e1) {} 
				catch (IOException e1) {} 
				catch (InvalidKeySpecException e1) {} 
	
				setFrameTitle(fileName, this);
			}
		}
	}
	/**
	 * Loads in files available to current user and displays them in a frame
	 * 
	 * @return void
	 */
	public void loadCLOUD()
	{
		saveFirst();
		if(cancelAction)
		{
			cancelAction = false;
			clearEverything();
			
			fileNames = DatabaseUtil.getUsersFileNames(User.currentUser);
			fileLabels = new ArrayList<JLabel>();
			int temp = fileNames.size();
			int cols = 0;
			
			loadFrame = new JDialog((JFrame) this, "Files You Can Access", true);
	
			loadCancel = new JButton("Cancel");
			loadCancel.addActionListener(this);
			if(fileNames.size() != 0)
			{
				if(fileNames.size() == 1)
				{
					loadFrame.setSize(160,fileNames.size()*100);
					loadFrame.setLayout(new GridLayout((fileNames.size()+1),1));
				}
				else if(fileNames.size() < 20)
				{
					loadFrame.setSize(160,fileNames.size()*50);
					loadFrame.setLayout(new GridLayout((fileNames.size()+1),1));
				}
				else
				{
					while(temp > 19)
					{
						temp = temp - 20;
						cols++;
					}
					loadFrame.setSize(160*cols,1100);
					loadFrame.setLayout(new GridLayout((21),1));
				}
				
				
				loadFrame.toFront();
				loadFrame.setResizable(false);
		
				for(int i = 0; i < fileNames.size(); i++)
				{
					fileLabels.add(new JLabel(fileNames.get(i)));
					loadFrame.add(fileLabels.get(i));
					fileLabels.get(i).addMouseListener(this);
				}
			
				loadFrame.add(loadCancel);
				loadFrame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
				loadFrame.setVisible(true);
			}
			else
				JOptionPane.showMessageDialog(null, "Nobody Loves you...");
		}
	}
	/**
	 * Allows users to select any file that they created to be deleted from the Cloud
	 * 
	 * @return void
	 */
	public void deleteCLOUD()
	{		

			fileNames = DatabaseUtil.getUsersFileNames(User.currentUser);
			deleteLabels = new ArrayList<JLabel>();
			
			int temp = fileNames.size();
			int cols = 0;
			
			loadFrame = new JDialog((JFrame) this, "Files You Can Delete", true);
	
			loadCancel = new JButton("Cancel");
			loadCancel.addActionListener(this);
			if(fileNames.size() != 0)
			{
		
		
				for(int i = 0; i < fileNames.size(); i++)
				{
					if(DatabaseUtil.isFileOwner(User.currentUser, fileNames.get(i)))
					{
						deleteLabels.add(new JLabel(fileNames.get(i)));
					}
				}
				
				for(int i = 0; i < deleteLabels.size(); i++)
				{
					loadFrame.add(deleteLabels.get(i));
					deleteLabels.get(i).addMouseListener(this);
				}
				
				if(deleteLabels.size() == 1)
				{
					loadFrame.setSize(160,deleteLabels.size()*100);
					loadFrame.setLayout(new GridLayout((deleteLabels.size()+1),1));
				}
				else if(fileNames.size() < 20)
				{
					loadFrame.setSize(160,deleteLabels.size()*50);
					loadFrame.setLayout(new GridLayout((deleteLabels.size()+1),1));
				}
				else
				{
					while(temp > 19)
					{
						temp = temp - 20;
						cols++;
					}
					loadFrame.setSize(160*cols,1100);
					loadFrame.setLayout(new GridLayout((21),1));
				}
				
				
				loadFrame.toFront();
				loadFrame.setResizable(false);
			
				if(deleteLabels.size() != 0)
				{
					loadFrame.add(loadCancel);
					loadFrame.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
					loadFrame.setVisible(true);
				}
				else
					JOptionPane.showMessageDialog(null, "No Files to Delete...");	
			}
			else
				JOptionPane.showMessageDialog(null, "Try creating something first...");	
		
	}
	/**
	 * Asks the user if they would like to save before loading or closing a file
	 * 
	 * @return void
	 */
	public void saveFirst()
	{
		int choice = JOptionPane.showConfirmDialog(null, "Would you like to save local file before you load a new one?");
		if(choice == JOptionPane.YES_OPTION)
		{
			cancelAction = true;
			String fileName = null;
			String filePath = null;
			String extension = "";
			JFileChooser chooser = new JFileChooser();
			chooser.setCurrentDirectory (new File ("."));
			int returnVal = chooser.showSaveDialog(this);
			if(returnVal == JFileChooser.APPROVE_OPTION) {
			      fileName = chooser.getSelectedFile().getName();
			      filePath = chooser.getSelectedFile().toString();
			      if(fileName.lastIndexOf(".") != -1){
			    	  extension = fileName.substring(fileName.lastIndexOf("."), fileName.length());
			      }
			}
			if(fileName == null){
				// Do Nothing
			}
			else if(invalidFileName(filePath,fileName)){
				JOptionPane.showMessageDialog(null, "Invalid File Name");
			}
			else if(!(extension.equals(".xml"))){
				JOptionPane.showMessageDialog(null, "File Must Have \".xml\" Extension");
			}
			else
			{
				boolean success = saveXML(filePath);
				if(success){
					JOptionPane.showMessageDialog(null,"The file: " + fileName + " has been successfully created.");
					setFrameTitle(fileName, this);
				}
				else{
					JOptionPane.showMessageDialog(null, "Error Saving File...");
				}
			}
			
		}
		else if (choice == JOptionPane.NO_OPTION){
			cancelAction = true;
		}
		
		clearEverything();

	}
	/**
	 * Clears all hashmaps and spreadsheets
	 * 
	 * @return void
	 */
	public void clearEverything()
	{
		if(formTable.getCellEditor() != null){
			formTable.getCellEditor().cancelCellEditing();
		}
		formTable.clearSelection();
		tm2.initiateValues();
		resetNameHash();
		
		Random r = new Random();
		x = r.nextInt(100);
		y = r.nextInt(100);
		
		String wCell = formTable.getColumnName(x) + y;
		nameMap.put("Waldo",wCell);
		altNameMap.put(wCell, "Waldo");
		
		try
		{
			Tools.addVariable("Waldo:" + wCell);
		} 
		catch (VariableAssignmentException e1) 
		{
			System.out.println("Waldo was not placed. :(");
		}
	}
}